/* freeircd alloc.h
 *
 * Iniciado em 09/05/2007
 */

#ifndef _ALLOC_H

#include <types.h>
#include <stdlib.h>
#include "debug.h"

extern inline void memerror(void *);

/* Nota: As macros neste ficheiro devem assegurar apenas as ligações das listas.
 *       So' aos membros next e prev devem ser atribuidos valores
 *
 * *NUNCA* devera' ser feito nenhum free()
 */

#define _alloc_bi_node(_lst)                                            \
        (                                                               \
        {                                                               \
                typeof(*_lst) _node;                                    \
                typeof(_lst) _plst=(_lst);                              \
                                                                        \
                if (*_plst == NULL)                                     \
                {                                                       \
                        _node=*_plst=malloc(sizeof(**_plst));           \
                        memerror(_node);                                \
                        _node->prev=NULL;                               \
                }                                                       \
                else                                                    \
                {                                                       \
                        _node=*_plst;                                   \
                                                                        \
                        while (_node != NULL)                           \
                        {                                               \
                                if (_node->next == NULL)                \
                                        break;                          \
                                                                        \
                                _node=_node->next;                      \
                        }                                               \
                                                                        \
                        _node->next=malloc(sizeof(*_node->next));       \
                        memerror(_node->next);                          \
                                                                        \
                        _node->next->prev=_node;                        \
                                                                        \
                        _node=_node->next;                              \
                }                                                       \
                                                                        \
                _node->next=NULL;                                       \
                                                                        \
                _node;                                                  \
        }                                                               \
        )

#define _rm_bi_node(_lst,_torm)                                         \
        (                                                               \
        {                                                               \
                typeof(_torm) _torm2=(_torm);                           \
                typeof(_lst) _lst2=(_lst);                              \
                                                                        \
                if (_torm2->prev == NULL)                               \
                {                                                       \
                        *_lst2=_torm2->next;                            \
                                                                        \
                        if (_torm2->next != NULL)                       \
                                _torm2->next->prev=NULL;                \
                }                                                       \
                else                                                    \
                {                                                       \
                        _torm2->prev->next=_torm2->next;                \
                                                                        \
                        if (_torm2->next != NULL)                       \
                                _torm2->next->prev=_torm2->prev;        \
                }                                                       \
        }                                                               \
        )

#define alloc_client(plst) _alloc_bi_node(plst)
#define rm_client(plst,torm) _rm_bi_node(plst,torm)
#define alloc_channel_in_user_list(plst) _alloc_bi_node(plst)
#define rm_channel_in_user_list(plst,torm) _rm_bi_node(plst,torm)
#define alloc_channel(plst) _alloc_bi_node(plst)
#define rm_channel(plst,torm) _rm_bi_node(plst,torm)
#define alloc_user_in_channel_list(plst) _alloc_bi_node(plst)
#define rm_user_in_channel_list(plst,torm) _rm_bi_node(plst,torm)
#define alloc_user_reg_list(plst) _alloc_bi_node(plst)
#define rm_user_reg_list(plst,torm) _rm_bi_node(plst,torm)
#define alloc_ban_list(plst) _alloc_bi_node(plst)
#define rm_ban_list(plst,torm) _rm_bi_node(plst,torm)
#define alloc_auser_list(plst) _alloc_bi_node(plst)
#define rm_auser_list(plst,torm) _rm_bi_node(plst,torm)
#define alloc_ajoin_list(plst) _alloc_bi_node(plst)
#define rm_ajoin_list(plst,torm) _rm_bi_node(plst,torm)
#define alloc_note_list(plst) _alloc_bi_node(plst)
#define rm_note_list(plst,torm) _rm_bi_node(plst,torm)
#define alloc_ircop_list(plst) _alloc_bi_node(plst)
#define rm_ircop_list(plst,torm) _rm_bi_node(plst,torm)

#define _ALLOC_H
#endif
